<?php
/**
 * 单件实例化 p 
 *
 * @filesource _db.class.php
 * @package peck
 * @subpackage _db
 * @version $id: 0.3, utf8, Sun Dec 20 21:25:28 CST 2009
 * @author LD King <kldscs[at]gmail.com>
 * @copyright Copyleft (D.) 2007 - 2010 MiFunny China Inc.
 * @link http://mifunny.info/
 * @example 
 * 
 *   //数据库配置
 *   $GLOBALS['__configs']['database'] => array(
        //第一个数据库连结
        'db0' => array(
            //数据库驱动, 参见 http://www.php.net/manual/en/pdo.drivers.php
		    'driver' => 'mysql',
		    'dsn' => 'mysql:dbname=test;host=locahost;port=3306',
		    'username' => 'test', 
		    'password' => 'test',
            'boost' => array(
                'SET NAMES utf8 COLLATE utf8_general_ci;',
                ), //连接既执行的一些SQL
		    //额外选项, 参见 http://www.php.net/manual/en/pdo.setattribute.php
    	    'options' => array( 
			    'ATTR_PERSISTENT' => FALSE, //是否使用长连接 	
		        'MYSQL_ATTR_USE_BUFFERED_QUERY' => TRUE,
   			    ),
            ),

            //第二个数据库连接
            'db1' => array(
                'driver' => 'sqlite',
                'dsn' => 'sqlite::memory:',
                'boost' => array(
                    'PRAGMA encoding = "UTF-8"',
                ), //连接既执行的一些SQL
            ),
		);
 * 
 *  如果是MySQL, dsn包括 :
 *   	'host' => '127.0.0.1',  //MySQL服务器IP地址
 *   	'port' => '3306',  //端口
 *   	'unix_socket' => '/var/mysql//mysql.sock', 
 *   	'dbname' => 'test', //数据库名
 */

class _db {
    /**
     * 
     * 现对象存储在
     *   $GOBALS['__objects']['db:mysql'];
     */
	
	private function __construct(){}
	private function __clone(){}
	
	/**
	 * 获得静态对象实例
     *
	 * @return self
	 */
    public static function object($offset=null){
        $dkey = empty($offset) ? 'default' : $offset;
        $key = 'database:'.$dkey;   
        $oo = '__objects';

        if( !empty($GLOBALS[$oo][$key]) 
          && is_object($GLOBALS[$oo][$key]) ){
            return $GLOBALS[$oo][$key];
        }

        $cc =& $GLOBALS['__configs']['database'];
		if ( empty($cc) ){
        	throw new LogicException('('.__METHOD__.')Error: configure array should be give !');
        }


        //判断配置数组`
        if( empty($offset) || empty($cc[$dkey]) ){
            reset($cc);
            $policy = current($cc);
        }else{
            $policy = $cc[$dkey];       
        }

        foreach(array('driver', 'dsn', 'username', 'password', 'boost', 'options') as $k){
            $policy[$k] = array_key_exists($k, $policy) ? $policy[$k] : null;
        }

        //Windows下使用MagicDB, Win里的PDO简直是个鸡肋！
		if ( extension_loaded('pdo_'.$policy['driver']) ){
            if( $policy['driver']=='mysql' and stripos(PHP_OS, 'win') === 0 ){
                $object = self::_initMySQL($policy); //MagicDB
            }else{
                require_once '_pdo.class.php';
                $object = new _pdo($policy);
            }

        }elseif( $policy['driver']=='mysql' ){
			$object = self::_initMySQL($policy); //MagicDB
        }else{
        	throw new LogicException('('.__METHOD__.')'."Error: pdo_{$policy['driver']} initialization failed, check your system configuration !");
            return false;
        }

        //循环执行boost中的SQL语句
        if( 0<count($policy['boost']) ){
            foreach($policy['boost'] as $v){
                $object->exec($v);
            }
        }//END boost
        
        $GLOBALS[$oo][$key] = $object;
        return $GLOBALS[$oo][$key];
	}//END func object

    /**
     * 重新连接数据库
     *
     */
    public static function reconnect($offset=null){
        $dkey = empty($offset) ? 'default' : $offset;
        $key = 'database:'.$dkey;   
        $oo = '__objects';
        if( !empty($GLOBALS[$oo][$key]) ){
            //unset($GLOBALS[$oo][$key]);
            $GLOBALS[$oo][$key] = null;
        } 
        return self::object($offset);
    }

	/**
	 * 初始化非PDO连接对象
	 *
	 * @param array $policy 配置数组
	 * 
	 * @return database object
	 */
	 private static function _initMySQL($policy){
		preg_match("/host=(.*?)($| |;)/i",$policy['dsn'],$host);
		preg_match("/port=(.*?)($| |;)/i",$policy['dsn'],$port);
		preg_match("/unix_socket=(.*?)($| |;)/i",$policy['dsn'],$unix_socket);
		preg_match("/dbname=(.*?)($| |;)/i",$policy['dsn'],$dbname);
		$policy['host'] = isset($host[1]) ? $host[1] : NULL;
		$policy['port'] = isset($port[1]) ? $port[1] : NULL;
		$policy['unix_socket'] = isset($unix_socket[1]) ? $unix_socket[1] : NULL;
		$policy['dbname'] = isset($dbname[1]) ? $dbname[1] : NULL; 

		//start MagicDB
		if( extension_loaded('mysqli') ){
			require_once '_mysqli.class.php';
        	return new _mysqli($policy);
		}else {
			require_once '_mysql.class.php';
        	return new _mysql($policy);
        }
    }//END func _initializeMagicDB

}//END class DB


